package rcp.iphex2.ui.projectexplorer;

import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.part.ViewPart;

import rcp.iphex2.model.AreaAnnotation;
import rcp.iphex2.model.ModelProvider;
import rcp.iphex2.model.Peak;
import rcp.iphex2.model.Project;
import rcp.iphex2.model.ProjectEntry;


public class ProjectExplorerView extends ViewPart {
	// private MyViewerComparator comparator;
	private TableViewer viewer;
	private Project activeProject;
	Composite parent;
	Menu tableMenu;
	TableColumn selectedColumn;

	public ProjectExplorerView() {
		// TODO Auto-generated constructor stub

	}

	public void setProject(Project project) {
		activeProject = project;
		//project.setProjectExplorerView(this);
		update(false);
	}

	public void update(boolean modelChanged) {
		if (viewer != null) {
			if (modelChanged) {
				for (TableColumn tc : viewer.getTable().getColumns()) {
					tc.dispose();
				}
				createColumns(parent, viewer);
				viewer.refresh();
			} else {
				viewer.refresh();
			}
		}
	}

	@Override
	public void createPartControl(Composite parent) {
		this.parent = parent;
		Project project = ModelProvider.INSTANCE.getProject("Default");
		setProject(project);
		createTableViewer(parent);
		createMenus();
		addMenu();
	}

	private void createTableViewer(Composite parent) {
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
		createColumns(parent, viewer);
		final Table table = viewer.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		viewer.setContentProvider(new ArrayContentProvider());
		// Get the content for the viewer, setInput will call getElements in the
		// contentProvider
		viewer.setInput(activeProject.getProjectEntries());
		// Make the selection available to other views
		getSite().setSelectionProvider(viewer);
		// Set the sorter for the table

		// Layout the viewer
		GridData gridData = new GridData();
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 2;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		viewer.getControl().setLayoutData(gridData);

	}

	private void createMenus() {
		final Menu headerMenu = new Menu(parent.getShell(), SWT.POP_UP);
		final MenuItem itemName = new MenuItem(headerMenu, SWT.BUTTON1);
		itemName.setText("Delete");
		itemName.addListener(SWT.Selection, new Listener() {
			@Override
			public void handleEvent(Event event) {

				AreaAnnotation areaAnnotation = activeProject.getAreaAnnotationFromName(selectedColumn.getText());
				if (areaAnnotation != null) {
					activeProject.removeAreaAnnotation(areaAnnotation);
					System.out.println("removing " + areaAnnotation.getName());
				}

			}
		});

		viewer.getTable().addListener(SWT.MenuDetect, new Listener() {
			@Override
			public void handleEvent(Event event) {
				Point pt = parent.getDisplay().map(null, viewer.getTable(), new Point(event.x, event.y));
				Rectangle clientArea = viewer.getTable().getClientArea();
				boolean header = clientArea.y <= pt.y && pt.y < (clientArea.y + viewer.getTable().getHeaderHeight());
				viewer.getTable().setMenu(header ? headerMenu : tableMenu);

				// locate the column where the klick was performed
				int widthSum = 0;
				// int index = 0;
				for (TableColumn tc : viewer.getTable().getColumns()) {
					if (pt.x > widthSum && pt.x < widthSum + tc.getWidth()) {
						// System.out.println("column " + index);
						// System.out.println(tc.getText());
						selectedColumn = tc;
					}
					widthSum += tc.getWidth();
					// index++;
				}
			}
		});

		viewer.getTable().addListener(SWT.Dispose, new Listener() {
			@Override
			public void handleEvent(Event event) {
				headerMenu.dispose();
				tableMenu.dispose();
			}
		});

	}

	// This will create the columns for the table
	private void createColumns(final Composite parent, final TableViewer viewer) {
		String[] titles = { "Filename", "Sample ID", "Peaklist Name" };
		int[] bounds = { 100, 100, 100 };

		TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0], 0);
		if (col != null) {
			col.setLabelProvider(new ColumnLabelProvider() {
				@Override
				public String getText(Object element) {
					ProjectEntry p = (ProjectEntry) element;
					return p.getMeasurement().filename;
				}
			});
		}

		col = createTableViewerColumn(titles[1], bounds[1], 1);
		if (col != null) {
			col.setLabelProvider(new ColumnLabelProvider() {
				@Override
				public String getText(Object element) {
					ProjectEntry p = (ProjectEntry) element;
					return p.getMeasurement().patientID;
				}
			});
		}
		col = createTableViewerColumn(titles[2], bounds[2], 2);
		if (col != null) {
			col.setLabelProvider(new ColumnLabelProvider() {
				@Override
				public String getText(Object element) {
					ProjectEntry p = (ProjectEntry) element;
					if (p.getPeaklist() != null) {
						return p.getPeaklist().getFilename();
					} else
						return "No Peaklist";
				}
			});
		}

		// show all meatainformation
		int i = 3;
		for (final String metainformationKey : activeProject.getMetainformationKeys()) {
			col = createTableViewerColumn(metainformationKey, 100, i);
			if (col != null) {
				col.setLabelProvider(new ColumnLabelProvider() {
					@Override
					public String getText(Object element) {
						ProjectEntry projectEntry = (ProjectEntry) element;
						if (projectEntry.getMetaInformation(metainformationKey) != null) {
							return projectEntry.getMetaInformation(metainformationKey);
						} else
							return "No Metainformation";
					}
				});
			}
			i++;
		}

		// show all areaAnnotations and matching peaklist info
		for (final AreaAnnotation areaAnnotation : activeProject.getAreaAnnotations()) {
			col = createTableViewerColumn(areaAnnotation.getName(), 100, i);
			if (col != null) {
				col.setLabelProvider(new ColumnLabelProvider() {
					@Override
					public String getText(Object element) {
						ProjectEntry projectEntry = (ProjectEntry) element;
						if (projectEntry.getPeaklist() != null) {
							Peak closestPeak = areaAnnotation.getClosestPeak(projectEntry.getPeaklist());
							return closestPeak.intensity + "";
						} else
							return "No Peaklist";
					}
				});
			}
			i++;
		}

	}

	private TableViewerColumn createTableViewerColumn(String title, int bound, final int colNumber) {

		// currently unused
		// check if column with name already exists
		for (TableColumn c : viewer.getTable().getColumns()) {
			if (c.getText().equals(title)) {
				return null;

			}
		}

		final TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
		final TableColumn column = viewerColumn.getColumn();
		column.setText(title);
		column.setWidth(bound);
		column.setResizable(true);
		column.setMoveable(true);
		return viewerColumn;
	}

	private void addMenu() {
		MenuManager menuManager = new MenuManager();
		tableMenu = menuManager.createContextMenu(viewer.getControl());
		viewer.getControl().setMenu(tableMenu);
		getSite().registerContextMenu(menuManager, viewer);
	}

	@Override
	public void setFocus() {
		// viewer.setInput(ModelProvider.INSTANCE.getProject("Default"));
		viewer.getControl().setFocus();
	}

	public Project getActiveProject() {
		return activeProject;
	}

}
